//////////////////////////////////////////////////////////////////////////
public:
	/// <summary>
	/// this function is used to set some external parameters in case of X Window
	/// </summary>
	/// <param name="argc"></param>
	/// <returns></returns>
	static int InitSystem(int argc, array<System::String^>^ argv)
	{
		array<IntPtr>^ _argv = gcnew array<IntPtr>(argc);
		try
		{
			vector<char*> vargv(argc);
			for (int i = 0; i < argc; i++)
			{
				_argv[i] = Marshal::StringToHGlobalAnsi(argv[i]);
				vargv[i] = (char*)_argv[i].ToPointer();
			}
			return cvInitSystem(argc, &vargv[0]);
		}
		finally
		{
			for (int i = 0; i < argc; i++)
			{
				if (_argv[i] != IntPtr::Zero)
				{
					Marshal::FreeHGlobal(_argv[i]);
				}
			}
		}
	}

	/// <summary>
	/// </summary>
	/// <returns></returns>
	static int StartWindowThread()
	{
		return cvStartWindowThread();
	}

	/// <summary>
	/// create window
	/// </summary>
	/// <param name="name"></param>
	/// <returns></returns>
	static int NamedWindow(System::String^ name, WindowMode flags)
	{
		auto_string _name(name);
		return cvNamedWindow(_name, (int)flags);
	}

	/// <summary>
	/// create window
	/// </summary>
	/// <returns></returns>
	static int NamedWindow(System::String^ name)
	{
		auto_string _name(name);
		return cvNamedWindow(_name);
	}

	/// <summary>
	/// display image within window (highgui windows remember their content)
	/// </summary>
	/// <param name="name"></param>
	static void ShowImage(System::String^ name, ManagedArr^ image)
	{
		auto_string _name(name);
		cvShowImage(_name, image->ToCvArrPointer());
	}

	/// <summary>
	/// resize/move window
	/// </summary>
	/// <param name="name"></param>
	/// <param name="width"></param>
	static void ResizeWindow(System::String^ name, int width, int height)
	{
		auto_string _name(name);
		cvResizeWindow(_name, width, height);
	}

	/// <summary>
	/// </summary>
	/// <param name="name"></param>
	/// <param name="x"></param>
	static void MoveWindow(System::String^ name, int x, int y)
	{
		auto_string _name(name);
		cvMoveWindow(_name, x, y);
	}

	/// <summary>
	/// destroy window and all the trackers associated with it
	/// </summary>
	static void DestroyWindow(System::String^ name)
	{
		auto_string _name(name);
		cvDestroyWindow(_name);
	}

	/// <summary>
	/// </summary>
	static void DestroyAllWindows()
	{
		cvDestroyAllWindows();
	}

	/// <summary>
	/// get native window handle (HWND in case of Win32 and Widget in case of X Window)
	/// </summary>
	/// <returns></returns>
	static IntPtr GetWindowHandle(System::String^ name)
	{
		auto_string _name(name);
		return IntPtr(cvGetWindowHandle(_name));
	}

	/// <summary>
	/// get name of highgui window given its native handle
	/// </summary>
	/// <returns></returns>
	static System::String^ GetWindowName(IntPtr window_handle)
	{
		return Marshal::PtrToStringAnsi(IntPtr((char*)cvGetWindowName((void*)window_handle.ToPointer())));
	}

	/// <summary>
	/// create trackbar and display it on top of given window, set callback
	/// </summary>
	/// <param name="trackbar_name"></param>
	/// <param name="window_name"></param>
	/// <param name="value"></param>
	/// <param name="count"></param>
	/// <returns></returns>
	static int CreateTrackbar(System::String^ trackbar_name, System::String^ window_name, IntPtr value, int count, TrackbarCallback^ on_change)
	{
		auto_string _trackbar_name(trackbar_name);
		auto_string _window_name(window_name);
		return cvCreateTrackbar(_trackbar_name, _window_name, (int*)value.ToPointer(), count, 
			(CvTrackbarCallback)Marshal::GetFunctionPointerForDelegate(on_change).ToPointer());
	}

	/// <summary>
	/// </summary>
	/// <param name="trackbar_name"></param>
	/// <param name="window_name"></param>
	/// <param name="value"></param>
	/// <param name="count"></param>
	/// <param name="on_change"></param>
	/// <returns></returns>
	static int CreateTrackbar2(System::String^ trackbar_name, System::String^ window_name, IntPtr value, int count, TrackbarCallback2^ on_change, IntPtr userdata)
	{
		auto_string _trackbar_name(trackbar_name);
		auto_string _window_name(window_name);
		return cvCreateTrackbar2(_trackbar_name, _window_name, (int*)value.ToPointer(), count, 
			(CvTrackbarCallback2)Marshal::GetFunctionPointerForDelegate(on_change).ToPointer(), (void*)userdata.ToPointer());
	}

	/// <summary>
	/// </summary>
	/// <param name="trackbar_name"></param>
	/// <param name="window_name"></param>
	/// <param name="value"></param>
	/// <param name="count"></param>
	/// <returns></returns>
	static int CreateTrackbar2(System::String^ trackbar_name, System::String^ window_name, IntPtr value, int count, TrackbarCallback2^ on_change)
	{
		auto_string _trackbar_name(trackbar_name);
		auto_string _window_name(window_name);
		return cvCreateTrackbar2(_trackbar_name, _window_name, (int*)value.ToPointer(), count, 
			(CvTrackbarCallback2)Marshal::GetFunctionPointerForDelegate(on_change).ToPointer());
	}

	/// <summary>
	/// retrieve or set trackbar position
	/// </summary>
	/// <param name="trackbar_name"></param>
	/// <returns></returns>
	static int GetTrackbarPos(System::String^ trackbar_name, System::String^ window_name)
	{
		auto_string _trackbar_name(trackbar_name);
		auto_string _window_name(window_name);
		return cvGetTrackbarPos(_trackbar_name, _window_name);
	}

	/// <summary>
	/// </summary>
	/// <param name="trackbar_name"></param>
	/// <param name="window_name"></param>
	static void SetTrackbarPos(System::String^ trackbar_name, System::String^ window_name, int pos)
	{
		auto_string _trackbar_name(trackbar_name);
		auto_string _window_name(window_name);
		cvSetTrackbarPos(_trackbar_name, _window_name, pos);
	}

	/// <summary>
	/// assign callback for mouse events
	/// </summary>
	/// <param name="window_name"></param>
	/// <param name="on_mouse"></param>
	static void SetMouseCallback(System::String^ window_name, MouseCallback^ on_mouse, IntPtr param)
	{
		auto_string _window_name(window_name);
		cvSetMouseCallback(_window_name, 
			(CvMouseCallback)Marshal::GetFunctionPointerForDelegate(on_mouse).ToPointer(), (void*)param.ToPointer());
	}

	/// <summary>
	/// assign callback for mouse events
	/// </summary>
	/// <param name="window_name"></param>
	static void SetMouseCallback(System::String^ window_name, MouseCallback^ on_mouse)
	{
		auto_string _window_name(window_name);
		cvSetMouseCallback(_window_name, 
			(CvMouseCallback)Marshal::GetFunctionPointerForDelegate(on_mouse).ToPointer());
	}

	/// <summary>
	/// load image from file
	/// iscolor can be a combination of above flags where CV_LOAD_IMAGE_UNCHANGED
	/// overrides the other flags
	/// using CV_LOAD_IMAGE_ANYCOLOR alone is equivalent to CV_LOAD_IMAGE_UNCHANGED
	/// unless CV_LOAD_IMAGE_ANYDEPTH is specified images are converted to 8bit
	/// </summary>
	/// <param name="filename"></param>
	/// <returns></returns>
	static ManagedImage^ LoadImage(System::String^ filename, LoadImageFlag iscolor)
	{
		auto_string _filename(filename);
		return gcnew ManagedImage(cvLoadImage(_filename, (int)iscolor), true);
	}

	/// <summary>
	/// load image from file
	/// iscolor can be a combination of above flags where CV_LOAD_IMAGE_UNCHANGED
	/// overrides the other flags
	/// using CV_LOAD_IMAGE_ANYCOLOR alone is equivalent to CV_LOAD_IMAGE_UNCHANGED
	/// unless CV_LOAD_IMAGE_ANYDEPTH is specified images are converted to 8bit
	/// </summary>
	/// <returns></returns>
	static ManagedImage^ LoadImage(System::String^ filename)
	{
		auto_string _filename(filename);
		return gcnew ManagedImage(cvLoadImage(_filename), true);
	}

	/// <summary>
	/// </summary>
	/// <param name="filename"></param>
	/// <returns></returns>
	static ManagedMat^ LoadImageM(System::String^ filename, LoadImageFlag iscolor)
	{
		auto_string _filename(filename);
		return gcnew ManagedMat(cvLoadImageM(_filename, (int)iscolor), true);
	}

	/// <summary>
	/// </summary>
	/// <returns></returns>
	static ManagedMat^ LoadImageM(System::String^ filename)
	{
		auto_string _filename(filename);
		return gcnew ManagedMat(cvLoadImageM(_filename), true);
	}

	/// <summary>
	/// save image to file
	/// </summary>
	/// <param name="filename"></param>
	/// <param name="image"></param>
	/// <returns></returns>
	static int SaveImage(System::String^ filename, ManagedArr^ image, array<int>^ params)
	{
		auto_string _filename(filename);
		pin_ptr<int> pparams = &params[0];
		return cvSaveImage(_filename, image->ToCvArrPointer(), pparams);
	}

	/// <summary>
	/// save image to file
	/// </summary>
	/// <param name="filename"></param>
	/// <returns></returns>
	static int SaveImage(System::String^ filename, ManagedArr^ image)
	{
		auto_string _filename(filename);
		return cvSaveImage(_filename, image->ToCvArrPointer());
	}

	/// <summary>
	/// decode image stored in the buffer
	/// </summary>
	/// <param name="buf"></param>
	/// <returns></returns>
	static ManagedImage^ DecodeImage(ManagedMat^ buf, LoadImageFlag iscolor)
	{
		return gcnew ManagedImage(cvDecodeImage(buf->ToCvMatPointer(), (int)iscolor), true);
	}

	/// <summary>
	/// decode image stored in the buffer
	/// </summary>
	/// <returns></returns>
	static ManagedImage^ DecodeImage(ManagedMat^ buf)
	{
		return gcnew ManagedImage(cvDecodeImage(buf->ToCvMatPointer()), true);
	}

	/// <summary>
	/// </summary>
	/// <param name="buf"></param>
	/// <returns></returns>
	static ManagedMat^ DecodeImageM(ManagedMat^ buf, LoadImageFlag iscolor)
	{
		return gcnew ManagedMat(cvDecodeImageM(buf->ToCvMatPointer(), (int)iscolor), true);
	}

	/// <summary>
	/// </summary>
	/// <returns></returns>
	static ManagedMat^ DecodeImageM(ManagedMat^ buf)
	{
		return gcnew ManagedMat(cvDecodeImageM(buf->ToCvMatPointer()), true);
	}

	/// <summary>
	/// encode image and store the result as a byte vector (single-row 8uC1 matrix)
	/// </summary>
	/// <param name="ext"></param>
	/// <param name="image"></param>
	/// <returns></returns>
	static ManagedMat^ EncodeImage(System::String^ ext, ManagedArr^ image, array<int>^ params)
	{
		auto_string _ext(ext);
		pin_ptr<int> pparams = &params[0];
		return gcnew ManagedMat(cvEncodeImage(_ext, image->ToCvArrPointer(), pparams), true);
	}

	/// <summary>
	/// encode image and store the result as a byte vector (single-row 8uC1 matrix)
	/// </summary>
	/// <param name="ext"></param>
	/// <returns></returns>
	static ManagedMat^ EncodeImage(System::String^ ext, ManagedArr^ image)
	{
		auto_string _ext(ext);
		return gcnew ManagedMat(cvEncodeImage(_ext, image->ToCvArrPointer()), true);
	}

	/// <summary>
	/// utility function: convert one image to another with optional vertical flip
	/// </summary>
	/// <param name="src"></param>
	/// <param name="dst"></param>
	static void ConvertImage(ManagedArr^ src, ManagedArr^ dst, ConvertImageFlag flags)
	{
		cvConvertImage(src->ToCvArrPointer(), dst->ToCvArrPointer(), (int)flags);
	}

	/// <summary>
	/// utility function: convert one image to another with optional vertical flip
	/// </summary>
	/// <param name="src"></param>
	static void ConvertImage(ManagedArr^ src, ManagedArr^ dst)
	{
		cvConvertImage(src->ToCvArrPointer(), dst->ToCvArrPointer());
	}

	/// <summary>
	/// wait for key event infinitely (delay<=0) or for "delay" milliseconds
	/// </summary>
	/// <returns></returns>
	static int WaitKey(int delay)
	{
		return cvWaitKey(delay);
	}

	/// <summary>
	/// wait for key event infinitely (delay<=0) or for "delay" milliseconds
	/// </summary>
	/// <returns></returns>
	static int WaitKey()
	{
		return cvWaitKey();
	}

	/// <summary>
	/// start capturing frames from video file
	/// </summary>
	/// <returns></returns>
	static ManagedCapture^ CreateFileCapture(System::String^ filename)
	{
		auto_string _filename(filename);
		return gcnew ManagedCapture(cvCreateFileCapture(_filename), true);
	}

	/// <summary>
	/// start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*)
	/// </summary>
	/// <returns></returns>
	static ManagedCapture^ CreateCameraCapture(CaptureDeviceFlag index)
	{
		return gcnew ManagedCapture(cvCreateCameraCapture((int)index), true);
	}

	/// <summary>
	/// grab a frame, return 1 on success, 0 on fail.
	/// this function is thought to be fast
	/// </summary>
	/// <returns></returns>
	static int GrabFrame(ManagedCapture^ capture)
	{
		return cvGrabFrame(capture->ToCvCapturePointer());
	}

	/// <summary>
	/// get the frame grabbed with cvGrabFrame(..)
	/// This function may apply some frame processing like
	/// frame decompression, flipping etc.
	/// !!!DO NOT RELEASE or MODIFY the retrieved frame!!!
	/// </summary>
	/// <param name="capture"></param>
	/// <returns></returns>
	static ManagedImage^ RetrieveFrame(ManagedCapture^ capture, CaptureDeviceFlag streamIdx)
	{
		return gcnew ManagedImage(cvRetrieveFrame(capture->ToCvCapturePointer(), (int)streamIdx), false);
	}

	/// <summary>
	/// get the frame grabbed with cvGrabFrame(..)
	/// This function may apply some frame processing like
	/// frame decompression, flipping etc.
	/// !!!DO NOT RELEASE or MODIFY the retrieved frame!!!
	/// </summary>
	/// <returns></returns>
	static ManagedImage^ RetrieveFrame(ManagedCapture^ capture)
	{
		return gcnew ManagedImage(cvRetrieveFrame(capture->ToCvCapturePointer()), false);
	}

	/// <summary>
	/// Just a combination of cvGrabFrame and cvRetrieveFrame
	/// !!!DO NOT RELEASE or MODIFY the retrieved frame!!!
	/// </summary>
	/// <returns></returns>
	static ManagedImage^ QueryFrame(ManagedCapture^ capture)
	{
		return gcnew ManagedImage(cvQueryFrame(capture->ToCvCapturePointer()), false);
	}

	/// <summary>
	/// stop capturing/reading and free resources
	/// </summary>
	static void ReleaseCapture(ManagedCapture^% capture)
	{
		CvCapture* pcapture = capture->ToCvCapturePointer();
		cvReleaseCapture(&pcapture);
		capture->m_pHandle = pcapture;
	}

	/// <summary>
	/// retrieve or set capture properties
	/// </summary>
	/// <param name="capture"></param>
	/// <returns></returns>
	static double GetCaptureProperty(ManagedCapture^ capture, CapturePropType property_id)
	{
		return cvGetCaptureProperty(capture->ToCvCapturePointer(), (int)property_id);
	}

	/// <summary>
	/// </summary>
	/// <param name="capture"></param>
	/// <param name="property_id"></param>
	/// <returns></returns>
	static int SetCaptureProperty(ManagedCapture^ capture, CapturePropType property_id, double value)
	{
		return cvSetCaptureProperty(capture->ToCvCapturePointer(), (int)property_id, value);
	}

	/// <summary>
	/// Return the type of the capturer (eg, CV_CAP_V4W, CV_CAP_UNICAP), which is unknown if created with CV_CAP_ANY
	/// </summary>
	/// <returns></returns>
	static int GetCaptureDomain(ManagedCapture^ capture)
	{
		return cvGetCaptureDomain(capture->ToCvCapturePointer());
	}

	/// <summary>
	/// initialize video file writer
	/// </summary>
	/// <param name="filename"></param>
	/// <param name="fourcc"></param>
	/// <param name="fps"></param>
	/// <param name="frame_size"></param>
	/// <returns></returns>
	static ManagedVideoWriter^ CreateVideoWriter(System::String^ filename, int fourcc, double fps, NAMESPACE::Size2D32s frame_size, int is_color)
	{
		auto_string _filename(filename);
		return gcnew ManagedVideoWriter(cvCreateVideoWriter(_filename, fourcc, fps, *(CvSize*)&frame_size, is_color), true);
	}

	/// <summary>
	/// initialize video file writer
	/// </summary>
	/// <param name="filename"></param>
	/// <param name="fourcc"></param>
	/// <param name="fps"></param>
	/// <returns></returns>
	static ManagedVideoWriter^ CreateVideoWriter(System::String^ filename, int fourcc, double fps, NAMESPACE::Size2D32s frame_size)
	{
		auto_string _filename(filename);
		return gcnew ManagedVideoWriter(cvCreateVideoWriter(_filename, fourcc, fps, *(CvSize*)&frame_size), true);
	}

	/// <summary>
	/// write frame to video file
	/// </summary>
	/// <param name="writer"></param>
	/// <returns></returns>
	static int WriteFrame(ManagedVideoWriter^ writer, ManagedImage^ image)
	{
		return cvWriteFrame(writer->ToCvVideoWriterPointer(), image->ToIplImagePointer());
	}

	/// <summary>
	/// close video file writer
	/// </summary>
	static void ReleaseVideoWriter(ManagedVideoWriter^% writer)
	{
		CvVideoWriter* pwriter = writer->ToCvVideoWriterPointer();
		cvReleaseVideoWriter(&pwriter);
		writer->m_pHandle = pwriter;
	}

	/// <summary>
	/// </summary>
	static void SetPreprocessFuncWin32(Win32WindowCallback^ on_preprocess)
	{
		cvSetPreprocessFuncWin32((CvWin32WindowCallback)Marshal::GetFunctionPointerForDelegate(on_preprocess).ToPointer());
	}

	/// <summary>
	/// </summary>
	static void SetPostprocessFuncWin32(Win32WindowCallback^ on_postprocess)
	{
		cvSetPostprocessFuncWin32((CvWin32WindowCallback)Marshal::GetFunctionPointerForDelegate(on_postprocess).ToPointer());
	}

//////////////////////////////////////////////////////////////////////////